using Godot;
using System;
namespace Views.Edit
{
    public class EditView : Control
    {
        #region Fields
        
        [Export]
        private Color _rulerBgColor = ColorUtil.FromHSV(0, 0, 0.1f);
        [Export]
        private Color _rulerFgColor = ColorUtil.FromHSV(0, 0, 0.5f);
        [Export]
        private Font _rulerScaleFont;
        private EditViewport _viewport;
        private EditCanvas _canvas;

        #endregion

        #region Propertys

        public EditViewport EditViewport
        {
            get
            {
                if (_viewport == null)
                    _viewport = GetNode<EditViewport>("Viewport");
                return _viewport;
            }
        }

        public EditCanvas EditCanvas
        {
            get
            {
                if (_canvas == null)
                    _canvas = EditViewport.EditCanvas;
                return _canvas;
            }
        }

        #endregion

        #region Godot API
        
        public override bool _ClipsInput()
        {
            return true;
        }
        
        public override void _Ready()
        {
            _rulerScaleFont = _rulerScaleFont ?? GetThemeDefaultFont();
        }

        public override void _Draw()
        {
            DrawRuler();
            DrawRect(new Rect2(Vector2.Zero, RectSize - new Vector2(0, 1)), _rulerFgColor, false);
        }

        #endregion

        #region Private Functions
        
        private void OnEditCanvasRectChanged()
        {
            EditViewport.Update();
            Update();
        }
        
        private int GetRulerStep(float scale)
        {
            var step = (int)Math.Round(16f / scale);
            return step <= 0 ? 1 : step;
        }

        private void DrawRulerScale(float start, float end, int step, float scale, float offset)
        {
            var h = 10;
            var j = 0;
            var n = 10;
            if (scale > 32)
                n = 1;
            else if (scale > 16)
                n = 2;
            else if (scale > 8)
                n = 5;
            else if (scale < 0.5f)
                n = 5;
            else if (scale < 0.25f)
                n = 2;
            for (var i = 0; i >= start; i -= step, j++)
            {
                var v = offset + i * scale;
                if (j % n == 0)
                {
                    DrawLine(new Vector2(v, 0), new Vector2(v, 15), _rulerFgColor, 1);
                    DrawString(_rulerScaleFont, new Vector2(v + 2, h), i.ToString(), _rulerFgColor);
                }
                else
                {
                    DrawLine(new Vector2(v, 11), new Vector2(v, 15), _rulerFgColor);
                }
            }
            j = 1;
            for (var i = step; i < end; i += step, j++)
            {
                var v = offset + i * scale;
                if (j % n == 0)
                {
                    DrawLine(new Vector2(v, 0), new Vector2(v, 15), _rulerFgColor, 1);
                    DrawString(_rulerScaleFont, new Vector2(v + 2, h), i.ToString(), _rulerFgColor);
                }
                else
                {
                    DrawLine(new Vector2(v, 11), new Vector2(v, 15), _rulerFgColor);
                }
            }
        }
        
        private void DrawRuler()
        {
            var scale = EditCanvas.Scale;
            var offset_x = EditCanvas.Position.x;
            var offset_y = EditCanvas.Position.y;
            var start_x = -((offset_x + 100) / scale);
            var start_y = -((offset_y + 100) / scale);
            var end_x = ((EditViewport.RectSize.x + 200) / scale) + start_x;
            var end_y = ((EditViewport.RectSize.y + 200) / scale) + start_y;
            var step = GetRulerStep(scale);

            DrawSetTransform(new Vector2(16, 1), 0, Vector2.One);
            var hRulerRect = new Rect2(0, 0, RectSize.x - 17, 15);
            DrawRect(hRulerRect, _rulerBgColor);
            DrawRulerScale(start_x, end_x, step, scale, offset_x);
            DrawLine(hRulerRect.BottomLeft(0, -1), hRulerRect.BottomRight(0, -1), _rulerFgColor);

            DrawSetTransform(new Vector2(16, 16), (float)((Math.PI / 180) * 90), Vector2.One);
            var vRulerRect = new Rect2(0, 0, RectSize.y - 17, 15);
            DrawRect(vRulerRect, _rulerBgColor);
            DrawRulerScale(start_y, end_y, step, scale, offset_y);
            DrawLine(vRulerRect.TopLeft(), vRulerRect.TopRight(), _rulerFgColor);
        }
        
        #endregion
    }
}
